#include <stdio.h>
#include <memory.h>

/*
 * 多种修饰符修饰变量，理清变量含义的方法：
 * 1.找到变量名；
 * 2.第一个修饰符表示该变量的类型；
 * 3.变量名与修饰符按优先级结合，每结合一个修饰符，则把（变量名+修饰符）变为一个新的变量newVar；
 * 4.该新变量newVar表示什么？
 *   如(*oldVar) => newVar，则newVar表示指针oldVar指向对象的类型；
 *   如(oldVar[8]) => newVar，则newVar表示数组oldVar中元素的类型。
 * */

int main() {
    // 1.数组指针（等价于二维数组）
    int (*arrPtr)[10] = NULL; // 数组指针必须用括号，因为变量名优先与[10]结合，其次再与*结合
    int matrix[3][10] = {0};  // 数组初始化为0，方式一（方式一是定义数组时，使用{0}赋初始值，固定写法，只能写0，不能写其他值）
    arrPtr = matrix; //
    // memset(matrix, 0, 30*sizeof(int));  // 数组初始化为0，方式二
    memset(matrix, 1, sizeof(matrix));  // 数组初始化为0，方式二

    // 数组的名字相当于数组第0个元素的地址，即 matrix == &matrix[0]
    printf("matrix=%d\n", matrix);  // 数组名称就是一个地址，即首元素地址
    printf("&matrix[0]=%d\n", &matrix[0]); // 首元素地址
    printf("matrix == &matrix[0] ? %d\n", matrix == &matrix[0]);  // 1 验证数组名字和首元素地址是否相等？是

    printf("&matrix=%d\n", &matrix);  // 6421872 对数组取地址，还是数组首元素地址，但是步长变为整个数组长度了
    int *matrixPtr = &matrix;  
    printf("&matrixPtr[1]=%d\n", &matrixPtr[1]);  // 6421876
    printf("&matrixPtr[1] - &matrix=%d\n", &matrixPtr[1] - matrixPtr);  // 1
    printf("&matrixPtr[1] - (int*)&matrix=%d\n", &matrixPtr[1] - (int*)matrixPtr);  // 1  两个int类型的指针相减，结果是地址相减，再除以4
    printf("(long)&matrixPtr[1] - (long)matrixPtr=%d\n", (long)&matrixPtr[1] - (long)matrixPtr);  // 4
    long addr1 = (long)&matrixPtr[1];
    long addr2 = (long)matrixPtr;
    printf("addr1 - addr2 = %d\n", addr1 - addr2);
    
    printf("&matrix[1] - matrix=%d\n", &matrix[1] - matrix);  // 1

    (*arrPtr)[2] = 5; // 等价于 matrix[0][2] = 5;
    ++arrPtr; // arrPtr指向二维数组第下一行
    (*arrPtr)[2] = 6; // 等价于matrix[1][2] = 6;
    printf("打印二维数组matrix：\n");
    for (int i = 0; i < 3; ++i) {
        for (int j = 0; j < 10; ++j) {
            printf("%d ", matrix[i][j]);
        }
        printf("\n");
    }
    //
    typedef int Array_t[10]; // typedef自定义一个类型Array_t，与变量含义分析方法一样，Array_t表示一个包含10个元素的数组，元素的类型位int
    Array_t a, *pa; // a是一个数组，pa是一个指向数组的指针
    pa = &a; //

    // 2.指针数组（也等价于二维数组）

    // 变量ptrArr优先与[10]结合，表示ptrArr为一个包含10个元素的数组，将ptrArr[10]转为newVar，
    // 则得到char *newVar，newVar的类型就是就是ptrArr这个数组元素的类型
    char *ptrArr[10]; // (char *)ptrArr[10];

    return 0;
}
